from datetime import datetime
from backend.db.database import redis_client
from backend.db.models import Client
from backend.db.database import get_db

# 心跳超时时间（30秒，超过则标记为离线）
HEARTBEAT_TIMEOUT = 30


# 1. 更新客户端心跳状态
def update_client_heartbeat(client_id: str, client_name: str, client_type: str):
    # 存储心跳时间到Redis（键：client:{client_id}:heartbeat，值：当前时间戳）
    redis_client.setex(
        name=f"client:{client_id}:heartbeat",
        time=HEARTBEAT_TIMEOUT * 2,  # 过期时间设为超时时间的2倍
        value=str(datetime.utcnow().timestamp())
    )

    # 更新数据库中的客户端信息
    db = next(get_db())
    client = db.query(Client).filter(Client.client_id == client_id).first()

    if client:
        client.last_heartbeat = datetime.utcnow()
        client.is_online = True
        client.client_name = client_name
    else:
        # 新增客户端记录
        new_client = Client(
            client_id=client_id,
            client_name=client_name,
            client_type=client_type,
            last_heartbeat=datetime.utcnow(),
            is_online=True
        )
        db.add(new_client)

    db.commit()


# 2. 检查客户端在线状态（定时任务）
def check_client_online_status():
    db = next(get_db())
    now = datetime.utcnow().timestamp()

    # 获取所有客户端ID
    client_keys = redis_client.keys("client:*:heartbeat")
    for key in client_keys:
        client_id = key.split(":")[1]
        last_heartbeat = float(redis_client.get(key) or 0)

        # 超时未心跳：标记为离线
        if now - last_heartbeat > HEARTBEAT_TIMEOUT:
            client = db.query(Client).filter(Client.client_id == client_id).first()
            if client and client.is_online:
                client.is_online = False
                db.commit()
                print(f"客户端 {client_id} 超时离线")


# 3. 获取所有客户端状态
def get_all_clients_status():
    db = next(get_db())
    clients = db.query(Client).all()
    return [
        {
            "client_id": c.client_id,
            "client_name": c.client_name,
            "client_type": c.client_type,
            "last_heartbeat": c.last_heartbeat.isoformat() if c.last_heartbeat else None,
            "is_online": c.is_online
        }
        for c in clients
    ]